package org.streets.context.internal;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.tapestry5.ioc.annotations.SubModule;
import org.apache.tapestry5.ioc.def.ModuleDef;
import org.slf4j.Logger;
import org.streets.context.definition.ContextDefinition;
import org.streets.context.definition.ModuleDefinition;
/**
 * 
 * @author dzb
 *
 */
public class ContextDefinitionImpl implements ContextDefinition {
	
	private final List<ModuleDefinition> _modules = new ArrayList<ModuleDefinition>();

	private boolean inited = false; 
	private final Logger logger;
	
	public ContextDefinitionImpl(Logger logger) {
		this.logger = logger;
	}

	public boolean isInited() {
		return inited;
	}

	public List<ModuleDefinition> getModules() {
		return _modules;
	}
	
	public ModuleDefinition getModule(String moduleId) {
		for (ModuleDefinition md : _modules) {
			if (md.getId().equals(moduleId)) {
				return md;
			}
		}
		return null;
	}
	
	public void clear() {		
		for (ModuleDefinition md : _modules) {
			((ModuleDefinitionImpl)md).clear();
		}
		_modules.clear();
	}
		
	@SuppressWarnings("unchecked")
	public void _init_(final Collection defs) {
		_modules.clear();
		Set<Class<?>> subs = new HashSet<Class<?>>();		
		for (Iterator iter = defs.iterator(); iter.hasNext();) {
			ModuleDef def = (ModuleDef) iter.next();
			SubModule sm = (SubModule) def.getBuilderClass().getAnnotation(SubModule.class);
			if (sm != null) {
				for (Class subClzz : sm.value()) {
					subs.add(subClzz);
				}
			}
		}
		// Exclude all sub modules
		for (Iterator iter = defs.iterator(); iter.hasNext();) {
			ModuleDef def = (ModuleDef) iter.next();
			if (!subs.contains(def.getBuilderClass())) {
				_modules.add(new ModuleDefinitionImpl(defs, def,null));
			}
		}
		//排序
		Collections.sort(_modules, new Comparator<ModuleDefinition>(){
			public int compare(ModuleDefinition o1, ModuleDefinition o2) {
				return o1.getIndex() - o2.getIndex();
			}
			
		});
		inited = true;
	}
}
